package isstra.eratostene;
import isstra.rendezvous.*;

import java.util.*;

class Filtro extends Thread{
	   private static int conta=0;
	   private int primo;
	   private Channel<Integer> chIn, chOut;
	   public Filtro( int primo, Channel<Integer> chIn ){
	      this.primo=primo; this.chIn=chIn;
	      start();
	   }
	   public void run(){
	      while( true ){
	         int x=chIn.receive();
	         if( x==0 ){
	            System.out.printf( "%6d", primo );
	            conta++;
	            if( conta%12==0 || chOut==null ) System.out.println();
	            if( chOut!=null ) chOut.send( x );
	            break;
	         }
	         if( x%primo != 0 ){
	            if( chOut==null ){
	                chOut=new ChannelX<Integer>();
	                @SuppressWarnings("unused")
					Filtro f=new Filtro( x, chOut );
	            }
	            else chOut.send( x );
	         }
	      }
	   }
	}//Filtro


class Generatore extends Thread{
   int n;
   Channel<Integer> c;
   public Generatore( int n ){
      this.n=n;
      c=new ChannelX<Integer>();
      @SuppressWarnings("unused")
	Filtro f=new Filtro( 2, c ); //creazione primo filtro
   }
   public void run(){
      for( int i=3; i<=n; i++ ){
         c.send( i );
         try{
	sleep( (int)(Math.random()*10) );
         }catch(InterruptedException e){}
      }
      c.send( 0 );
   }
}//Generatore

public class Crivello{
	public static void main( String []args ){
		System.out.println("Crivello di Eratostene Parallelo");
	    System.out.println("Trova i numeri primi tra 2 e N");
	    @SuppressWarnings("resource")
		Scanner sc=new Scanner( System.in );
	    System.out.print("N=");
	    int n=sc.nextInt();
	    Generatore g=new Generatore( n );
	    g.start();
	}
}//Crivello

